﻿using System;
using System.Text;
using System.IO;
using System.Xml;


namespace VCC.Site.Components
{
    public class Base64StreamReader : Stream
    {
        private static XmlReaderSettings InitXmlReaderSettings()
        {
            return new XmlReaderSettings { ConformanceLevel = ConformanceLevel.Auto, CloseInput = false };
        }

        private Stream TheStream;

        private XmlReader xw;



        public Base64StreamReader(Stream stream)
        {
            TheStream = stream;
        }



        public override bool CanRead
        {
            get { return TheStream.CanRead; }
        }



        public override bool CanSeek
        {
            get { return TheStream.CanSeek; }
        }



        public override bool CanWrite
        {
            get { return TheStream.CanWrite; }
        }



        public override void Flush()
        {

        }



        public override void Close()
        {
            xw.Close();
        }



        public override long Length
        {
            get { return TheStream.Length; }
        }



        public override long Position
        {
            get { return TheStream.Position; }
            set { throw new NotImplementedException(); }
        }



        private bool _movedToContent;

        public override int Read(byte[] buffer, int offset, int count)
        {
            if (!_movedToContent)
            {
                xw = XmlReader.Create(TheStream, InitXmlReaderSettings());

                xw.MoveToContent();

                _movedToContent = true;
            }

            /* use 
             * int readed = xw.ReadElementContentAsBase64( buffer, offset, count );
             * for Base64 encoding
             */
            int readed = xw.ReadContentAsBase64(buffer, offset, count);

            return readed;
        }

        public override long Seek(long offset, SeekOrigin origin)
        {
            throw new NotImplementedException();
        }



        public override void SetLength(long value)
        {
            throw new NotImplementedException();
        }

        public override void Write(byte[] buffer, int offset, int count)
        {

        }
    }



    public class Base64StreamWriter : Stream
    {

        private static XmlWriterSettings InitXmlWriterSettings()
        {

            return new XmlWriterSettings
            {
                ConformanceLevel = ConformanceLevel.Auto,
                Encoding = Encoding.ASCII,
                OmitXmlDeclaration = true,
                CloseOutput = true
            };

        }



        private Stream TheStream;

        private XmlWriter xw;



        public Base64StreamWriter(Stream stream)
        {

            TheStream = stream;

            xw = XmlWriter.Create(stream, InitXmlWriterSettings());

            xw.WriteStartElement("data");

        }



        public override bool CanRead
        {

            get { return TheStream.CanRead; }

        }



        public override bool CanSeek
        {

            get { return TheStream.CanSeek; }

        }



        public override bool CanWrite
        {

            get { return TheStream.CanWrite; }

        }



        public override void Close()
        {

            if (xw.WriteState != WriteState.Closed)
            {

                xw.WriteEndElement();

                xw.Close();

            }

            base.Close();

        }



        public override void Flush()
        {

            xw.Flush();

        }



        public override long Length
        {

            get
            {

                return TheStream.Length;

            }

        }



        public override long Position
        {

            get
            {

                return TheStream.Position;

            }

            set
            {

                throw new NotImplementedException();

            }

        }



        public override int Read(byte[] buffer, int offset, int count)
        {

            throw new NotImplementedException();

        }



        public override long Seek(long offset, SeekOrigin origin)
        {

            throw new NotImplementedException();

        }



        public override void SetLength(long value)
        {

            throw new NotImplementedException();

        }



        public override void Write(byte[] buffer, int offset, int count)
        {

            /* use 

             * xw.WriteBase64( buffer, offset, count ); 

             * for Base64 encoding

             */

            xw.WriteBase64(buffer, offset, count);

        }

    }
}
